import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;
import org.junit.jupiter.api.Test;

public class MuilThreadTest2 {

    /**
     * 每次并发线程数
     */
    private static final Integer THREAD_NUMS = 10;
    /**
     * 执行次数
     */
    private static final Integer TIMES = 3;
    /**
     * 每次之间的时间间隔（ms）
     */
    private static final Integer SLEEP = 1000;
    /**
     * 主线程等待时长（ms）
     */
    private static final Long TOTAL_SLEEP = 60*1000L;

    /**
     * 去重记录集合，方便查看是否存在线程安全问题
     */
    private static Map<Object, String> distinctMap = new ConcurrentHashMap<>();

    /**
     * 每次启动N个线程，每隔1S执行一次
     * 共执行M次
     * 由于测试类执行，主线程走完会强制结束所有线程
     * 所以进行模拟无限等待5*60*1000 即5分钟
     */
    @Test
    public void test(){
        for(int i = 0; i< TIMES; i++){
            try{
                mutiThreadCounter();
                Thread.sleep(SLEEP);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        toWait();

        System.out.println(distinctMap.size());
    }

    private void mutiThreadCounter() throws Exception{
        final CyclicBarrier barrier = new CyclicBarrier(THREAD_NUMS);
        for (int i = 0; i < THREAD_NUMS; i++) {
            final long num = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        barrier.await();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    testThread(num);
                }
            }).start();
        }
    }

    private void toWait(){
        try {
            Thread.sleep(TOTAL_SLEEP);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void testThread(long num) {
        System.out.println("线程" + num + "exute..." + System.currentTimeMillis());
        try {
            Thread.sleep(500L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程" + num + "end..." + System.currentTimeMillis());
    }

}
